package com.z.kq.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageInfo;
import com.z.common.aop.annotation.Log;
import com.z.common.aop.enums.BusinessType;
import com.z.common.exception.BusinessException;
import com.z.common.web.base.BaseController;
import com.z.common.web.vo.request.PageVo;
import com.z.common.web.vo.response.Result;
import com.z.kq.entity.Leave;
import com.z.kq.service.ILeaveService;
import com.z.sys.entity.User;
import com.z.sys.service.IUserService;
import io.swagger.annotations.ApiOperation;
import org.camunda.bpm.engine.HistoryService;
import org.camunda.bpm.engine.RuntimeService;
import org.camunda.bpm.engine.TaskService;
import org.camunda.bpm.engine.history.HistoricActivityInstance;
import org.camunda.bpm.engine.runtime.ActivityInstance;
import org.camunda.bpm.engine.task.Task;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 请假管理Controller
 *
 * @author z
 * @date 2023-03-06
 */
@RestController
@RequestMapping("/kq/leave")
public class LeaveController extends BaseController {

    private String prefix = "kq/leave";

    @Autowired
    private ILeaveService leaveService;

    @Autowired
    private TaskService taskService;
    @Resource
    private RuntimeService runtimeService;
    @Resource
    private HistoryService historyService;

    @Autowired
    private IUserService userService;

    @GetMapping("/main")
    public ModelAndView main() {
        return jumpPage(prefix + "/main");
    }

    /**
     * 查询请假管理列表
     */
    @ResponseBody
    @GetMapping("/data")
    @Log(title = "请销假管理", describe = "查询请假数据", type = BusinessType.QUERY)
    public Result list(@ModelAttribute Leave leave, PageVo pageVo) {
        PageInfo<Leave> pageInfo = leaveService.selectLeavePage(leave, pageVo);
        return Result.table(pageInfo);
    }

    /**
     * 新增请假管理
     */
    @GetMapping("/add")
    public ModelAndView add() {
        return jumpPage(prefix + "/add");
    }

    /**
     * 新增请假管理
     */
    @ResponseBody
    @PostMapping("/save")
    @Log(title = "请销假管理", describe = "新增请假数据", type = BusinessType.ADD)
    public Result save(@RequestBody Leave leave) {
        return Result.decide(leaveService.save(leave));
    }

    /**
     * 新增请假管理
     */
    @ResponseBody
    @PostMapping("/saveByProId")
    @Log(title = "请销假管理", describe = "新增请假数据", type = BusinessType.ADD)
    public Result saveByProId(@RequestBody Leave leave) {
        Leave leave1 = leaveService.getOne(new QueryWrapper<Leave>().eq("process_id", leave.getProcessId()).eq("del", "0"));
        if(leave1 != null && leave1.getId() != null){
            BeanUtils.copyProperties(leave, leave1,"id");
        }else {
            leave1 = leave;
        }
        return Result.decide(leaveService.saveOrUpdate(leave1));
    }

    /**
     * 修改请假管理
     */
    @GetMapping("/edit")
    public ModelAndView edit(Long id, String processId, ModelMap map) {
        Leave leave =leaveService.getById(id);
        if(leave == null){
            leave = new Leave();
            leave.setProcessId( processId);
        }
        map.put("leave", leave);
        return jumpPage(prefix + "/edit");
    }

    /**
     * 请假起草页面
     */
    @GetMapping("/proEdit")
    public ModelAndView proEdit( String processId, ModelMap map) {
        Task task = taskService.createTaskQuery().processInstanceId(processId).singleResult();
        String userId = task.getAssignee();
        User user = userService.getById(userId);
        Leave leave = new Leave();
        leave.setProcessTitle(user.getUsername() + "的请假流程");
        leave.setUserId(userId);
        leave.setUsername(user.getUsername());
        leave.setUserSn(user.getUserSn());
        leave.setProcessId(processId);
        map.put("leave", leave);
        return jumpPage(prefix + "/proEdit");
    }

    /**
     * 请假审批页面
     */
    @GetMapping("/proAudit")
    public ModelAndView proAudit( String taskId, ModelMap map) {
        Task task = taskService.createTaskQuery().taskId(taskId).initializeFormKeys().singleResult();
        String formKey = task.getFormKey();
        String id = task.getProcessInstanceId();
        Leave leave =leaveService.getOne(new QueryWrapper<Leave>().eq("process_id", id).eq("del", "0"));
        if(leave == null){
            leave = new Leave();
            leave.setProcessId(id);
        }
        map.put("leave", leave);
        if(task.getName().equals("用户发起")){
            return jumpPage(prefix + "/proEdit");

        }
        return jumpPage(prefix + "/proAudit");
    }

    /**
     * 流程发起页面
     * @param processId
     * @param model
     * @return
     */
    @GetMapping("/{processId}")
    public ModelAndView getForm(@PathVariable String processId, Model model) {

        String url = "/kq/leave/proEdit?processId=" + processId;
        model.addAttribute("url", url);
        model.addAttribute("id", "/kq/process/viewBpmn?id=" + processId);
        return jumpPage(prefix + "/form");
    }
    /**
     * 修改请假管理
     */
    @ResponseBody
    @PutMapping("/update")
    @Log(title = "请销假管理", describe = "修改请假数据", type = BusinessType.EDIT)
    public Result update(@RequestBody Leave leave) {
        return Result.decide(leaveService.updateById(leave));
    }

    /**
     * 删除请假管理
     */
    @ResponseBody
    @DeleteMapping("/batchRemove")
    @Log(title = "请销假管理", describe = "批量删除请假数据", type = BusinessType.REMOVE)
    public Result batchRemove(String ids) {
        return Result.decide(leaveService.removeByIds(Arrays.asList(ids.split(","))));
    }

    /**
     * 删除请假管理
     */
    @ResponseBody
    @DeleteMapping("/remove/{id}")
    @Log(title = "请销假管理", describe = "删除请假数据", type = BusinessType.REMOVE)
    public Result remove(@PathVariable("id") Long id) {
        return Result.decide(leaveService.removeById(id));
    }

    @ApiOperation(value = "请假审批-同意")
    @PostMapping("/next/{instanceId}")
    @ResponseBody
    public Result submitForm(@PathVariable String instanceId, @RequestBody String params) {
        try {
            JSONObject o = JSON.parseObject(params);
            boolean flag = o.getBoolean("flag");
            String auditId = o.getString("auditId");
            Task task = taskService.createTaskQuery().processInstanceId(instanceId).singleResult();

            Map<String, Object> map = new HashMap<>();
            map.put("approve_leader", flag);
            taskService.complete(task.getId(), map);
            task = taskService.createTaskQuery().processInstanceId(instanceId).singleResult();
            if(task == null){
                return Result.success("流程结束");
            }
            taskService.setAssignee(task.getId(), auditId);

        }catch (Exception e){
            e.printStackTrace();
            return Result.error(e.getMessage());
        }
        return Result.success();
    }

    @ApiOperation(value = "请假审批-驳回")
    @PostMapping("/back/{instanceId}")
    @ResponseBody
    public Result back(@PathVariable String instanceId, @RequestBody String params) {
        try {
            JSONObject o = JSON.parseObject(params);
            boolean flag = o.getBoolean("flag");
            if(flag){
                throw new BusinessException("参数异常");
            }

/*
            // 查询流程实例ID为processInstanceId的所有历史任务
            List<HistoricTaskInstance> historicTasks = historyService.createHistoricTaskInstanceQuery()
                    .processInstanceId(instanceId)
                    .orderByHistoricTaskInstanceEndTime().desc()
                    .list();

// 获取上一个已完成任务的名称
            String previousTaskName = "",previousAssignee = "";
            for (HistoricTaskInstance historicTask : historicTasks) {
                if (!historicTask.getEndTime().equals(null)) {
                    previousTaskName = historicTask.getName();
                    previousAssignee = historicTask.getAssignee();
                    break;
                }
            }
            Task currentTask = taskService.createTaskQuery().processInstanceId(instanceId).singleResult();
            if (currentTask != null) {
                // 驳回当前任务并设置被驳回人为原任务执行人
                Task rejectedTask = taskService.newTask(currentTask.getId());
                rejectedTask.setAssignee(previousAssignee);
                rejectedTask.setName(previousTaskName);
                taskService.saveTask(rejectedTask);

                // 完成当前任务并将审批流程返回到驳回节点
                taskService.complete(currentTask.getId());

            } else {
                // 没有找到活动中的任务，可能已经结束了或者不存在。
            }*/
            String processInstanceId=instanceId;
            String message="项目的金额款项结算不正确";
            Task task = taskService.createTaskQuery()
                    .processInstanceId(processInstanceId)
                    .singleResult();
            ActivityInstance tree = runtimeService.getActivityInstance(processInstanceId);
            List<HistoricActivityInstance> resultList = historyService
                    .createHistoricActivityInstanceQuery()
                    .processInstanceId(processInstanceId)
                    .activityType("userTask")
                    .finished()
                    .orderByHistoricActivityInstanceEndTime()
                    .asc()
                    .list();
            //得到第一个任务节点的id
            HistoricActivityInstance historicActivityInstance = resultList.get(0);
            String toActId = historicActivityInstance.getActivityId();
            String assignee = historicActivityInstance.getAssignee();
            //设置流程中的可变参数
            Map<String, Object> taskVariable = new HashMap<>(2);
            taskVariable.put("user", assignee);
            taskVariable.put("formName", "项目建设");
            taskVariable.put("assignee", assignee);
            taskService.createComment(task.getId(), processInstanceId, "驳回原因:" + message);
            runtimeService.createProcessInstanceModification(processInstanceId)
                    .cancelActivityInstance(getInstanceIdForActivity(tree, task.getTaskDefinitionKey()))//关闭相关任务
                    .setAnnotation("进行了驳回到第一个任务节点操作")
                    .startBeforeActivity(toActId)//启动目标活动节点
                    .setVariables(taskVariable)//流程的可变参数赋值
                    .execute();
            task = taskService.createTaskQuery().processInstanceId(instanceId).singleResult();
            taskService.setAssignee(task.getId(), assignee);
        }catch (Exception e){
            e.printStackTrace();
            return Result.error(e.getMessage());
        }
        return Result.success();
    }


    private String getInstanceIdForActivity(ActivityInstance activityInstance, String activityId) {
        ActivityInstance instance = getChildInstanceForActivity(activityInstance, activityId);
        if (instance != null) {
            return instance.getId();
        }
        return null;
    }

    private ActivityInstance getChildInstanceForActivity(ActivityInstance activityInstance, String activityId) {
        if (activityId.equals(activityInstance.getActivityId())) {
            return activityInstance;
        }
        for (ActivityInstance childInstance : activityInstance.getChildActivityInstances()) {
            ActivityInstance instance = getChildInstanceForActivity(childInstance, activityId);
            if (instance != null) {
                return instance;
            }
        }
        return null;
    }
}
